
#include <fat.h>

#include "c_Engine.h"
#include "c_Sprite.h"

#include "c_IPv4_Address.h"

wiigi::c_IPv4_Address wiigi::c_IPv4_Address::m_LocalAddress;

/**
 * default constructor
 */
wiigi::c_Engine::c_Engine( void )
:
   m_CurrentFrameBuffer( 0 ),
   m_GP_FIFO( 0 ),
   m_DrawQ( ),
   m_VisibleArea( ),    //Default constructor
   m_ConsoleFB( 0 ),
   m_FreeSprites(  )    //Default constructor
      
{
   for( u32 Idx = 0; Idx < d_NumberFrameBuffers; Idx++ )
   {
      m_FrameBuffer[ 0 ] = 0;
   }
   return;
}

/**
 * destructor
 */
wiigi::c_Engine::~c_Engine( void )
{
   
   return;
}
 
/**
 * Entry point to engine
 *
 * @param argc Usual 'argc' as supplied to main()
 * @param argc Usual 'argv' as supplied to main()
 *
 * @retval Normal system error code as would normally be returned by main()
 */ 
int wiigi::c_Engine::startEngine(int argc, char **argv)
{
   // Initialize filesystem to load from SD Card
	fatInitDefault();
   
   initVideo();
   
   initSprites();
   
   initInput();
   
   if( checkFlags( d_InitNetwork ) )
   {
      initNetwork();
   }
      
   runApp();
   
   closeVideo();
   
   return 0;
}

/**
 * Adds a application state to the state list maintained by this engine
 *
 * @param State State object to be added
 */
void wiigi::c_Engine::addState( c_AppState* State )
{
   const std::string& StateName = State->getName();

   State->setEngine( this );
   
   if( m_States.empty() )
   {
      m_CurrentStateName = StateName;
   }

   m_States.insert( make_pair( StateName, State ) );
   
   return;
}

/**
 * Handles the execution of the users application states.
 */
void wiigi::c_Engine::runApp( void )
{
   m_NextStateName.clear();
   
   c_AppState* State;
   State = m_States[ m_CurrentStateName ];
   
   updateDisplay();
   
   State->Enter();

   for(;;)
   {
      c_Sprite::setupDrawing();
      
      m_NextStateName = m_CurrentStateName;
      
      State->Run();
      
      updateDisplay();
      
      scanInputDevices();
            
      if(   m_NextStateName == "EXIT" 
         || checkFlags( d_HomePressed ) )
      {
         State->Exit();
         break;
      }
      else if( m_NextStateName != m_CurrentStateName )
      {
         State->Exit();

         State = m_States[ m_NextStateName ];

         State->Enter();
      }

   }
   
   return;
}
